#include "brush.h"
#include "input.h"
#include "control.h"
#include "particleSystem.h"
#include "skeletalDrawing.h"

Brush::Brush(){

name="brush";
drawType=DRAW_SPRITE;

color=Vector4f(1,1,1,1);
scale=Vector3f(0.1,0.1,0.1);
pNormal=Vector3f(0.0,0.0,1.0);
sceneShaderID="color";
depthShaderID="depthColor";
textureID="NULL";

bTextured=false;
bUseShader=true;
bFullBright=true;
bDrawOrientation=false;

drawing=NULL;
drawCharacter=NULL;
bMouseControlled=true;
charPart="";                  //the part that holds the particleSystem

calcLoc=Vector3f(0.0,0.0,0.0);                 //the location of the drawn Particle

menuType.clear();
menuProp.clear();
menuIcon.clear();
}

Brush::~Brush(){

}

void Brush::update(double deltaTime){

     string myString;

     renderer->pick(input->mouseX,input->mouseY);

     if (input->worldTarget && bMouseControlled)
       {
       myString=input->worldTarget->name;
       if (myString=="grid" || myString=="ground" || myString =="flexGrid" || myString =="ragDoll")
         {
         location=input->mouse3D;
         if (!drawCharacter)        //if we're drawing on the floor - translate a bit up
           location.y+=0.01;
           //location.z+=0.1;       //for drawing onto a grid...
        if (drawCharacter && !input->bShiftDown)
           determineDrawing();
         //painting, segmenting, etc...

         //add a segment everytime we start pressing the mouse button...
         if (input->startPressLeftBtn==1 && drawing!=NULL && !input->bShiftDown && drawing->drawType==DRAW_PARTICLES_LINE && input->hudTarget==NULL)
           {
           drawing->addSegment();
           }

         if (input->pressedLeft && !input->hudTarget && controller->state==MOVECURSORSTATE && !input->focusButton)
           paint();
         if (input->pressedRight && !input->hudTarget && controller->state==MOVECURSORSTATE && !input->focusButton)
           //erase();
           skin();
         }
       }
}

void Brush::paint(){

    if (fabs(input->mouseVector.length())>0)  //only draw particles if mouse is moving! But what if we use this to load from a file?
      {
        drawing->addParticles(1);
        calcLocation();
        drawing->particles[drawing->particles.size()-1].location=Vector4f(calcLoc.x,calcLoc.y,calcLoc.z,scale.x*0.1);
        drawing->particles[drawing->particles.size()-1].normal=pNormal;
        drawing->particles[drawing->particles.size()-1].color=color;
        drawing->particles[drawing->particles.size()-1].texCoord=Vector3f(color.r,color.g,color.b);     //texCoord holds color
        drawing->particles[drawing->particles.size()-1].birth=float(glutGet(GLUT_ELAPSED_TIME))/1000.0; //particle creation time in seconds
        input->numParticles++;
      }
}

void Brush::erase(){

    if (drawCharacter)
      calcLocation();
    else
      calcLoc=location-drawing->location;

    for (unsigned int i=0;i<drawing->particles.size();i++)
      {
      Vector4f loc=drawing->particles[i].location;
      Vector3f distance=calcLoc - Vector3f(loc.x,loc.y,loc.z);
      if (scale.x>distance.length())
          drawing->deleteParticle(i);
          //drawing->particles[i].color=Vector4f(1,0,0,1);
      }
    input->numParticles--;
}

void Brush::skin(){

    SkeletalDrawing* skel =dynamic_cast<SkeletalDrawing*>(drawing);
    if (!skel){
        cout << "drawing cannot be skinned" << endl;
        return;
        }

    calcLoc=location-drawing->location;

    //calcLocation();

    for (unsigned int pID=0;pID<drawing->particles.size();pID++){           //go through particles

        //find out where the brush is in relation to the particle
        Vector4f loc=drawing->particles[pID].location;
        Vector3f distance=calcLoc - Vector3f(loc.x,loc.y,loc.z);

        ///within brush range
        if (scale.x>distance.length()){

            ///single bone skinning
            if (input->selectedActors.size()==1){
                //find bone
                for (uint boneID=0; boneID<skel->bones.size();boneID++)
                    if (skel->bones[boneID]==input->selectedActors[0]){
                        skel->singleSkin(pID,boneID);                       //skin particles with this bone
                    }


            ///multi-bone skinning
            }else{
                int boneCount=0;                //position in bone array
                int multiID[]={-1,-1,-1,-1};    // array for up to 4 bones to be used for weighting

                for (uint selectCount=0; selectCount < input->selectedActors.size(); selectCount++){        //go through all selected actors
                    for (uint boneID=0; boneID < skel->bones.size();boneID++){                              //go through all bones for each selected actor
                        if (skel->bones[boneID]==input->selectedActors[selectCount] && boneCount < 4)       //if a selected actor is also a bone
                            multiID[boneCount++]=boneID;                                                    //assign to list of bones to be weighted
                    }//end all bones
                }// end all selected actors
                skel->multiSkin(pID,multiID);   //skin particle with up to 4 bones

            }//end multi-bone skinning

        }//end particles in brushrange

    }//end all particles
}

void Brush::determineDrawing(){
}

void Brush::calcLocation(){

Matrix4f invmDrawing;
Matrix4f mResult;
Vector4f calc;


invmDrawing=drawing->baseMatrix.inverse();     //todo: use a faster inverse() function
mResult=invmDrawing * baseMatrix ;

calc = mResult * Vector4f(0,0,0,1);
calcLoc = Vector3f(calc.x/calc.w , calc.y/calc.w , calc.z/calc.w);

}

void Brush::create(){

renderer->addActor(this);
std::cout << "created a brush \n";
}
